package com.andreani.snore_counter;

import java.io.File;
import java.io.IOException;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.IBinder;
import android.os.PowerManager;
import android.util.Log;


public class SnoreCounterService extends Service {

	private MyServiceBinder mBinder;
	private PowerManager.WakeLock wl; //TODO IMPLEMENT THE WAKELOCK
	private AudioProcessing mThread;
	private final String CUSTOM_ACTION = "com.andreani.snore_counter.NEW_MSG";
	private final String MSG = "CUSTOM_MSG";
	private int baseline;
	
	
	@Override
	public void onCreate()
	{
		Log.v(getClass().getName(),"onCreate");
		PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
		wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "snore_counter");
		wl.acquire();
		mBinder = new MyServiceBinder();
		mThread = new AudioProcessing();
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		Log.v(getClass().getName(),"onBind");
		return mBinder;
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId)
	{
		Log.v(getClass().getName(),"onStartCommand");
		return START_STICKY;
	}
	
	
	class AudioProcessing extends Thread
	{
		private MediaRecorder recorder;
		
		private boolean stopped = false;
		
		public AudioProcessing(){android.os.Process.setThreadPriority(
			android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); 
			start();
		} 
		
		@Override
		public void run(){
			Log.v(getClass().getName(),"AudioProcessing: run ");
			
			startRecording();
			determineBaseline();  
			countSnores();
   		 	recorder.stop();
   		 	recorder.reset();   
   		 	recorder.release();
   		
		}
		
		private void countSnores() {
			Log.v(getClass().getName(),"AudioProcessing: countSnores ");
			int runs = 0;
			while(!stopped)
   		 	{
				runs++;
				if(runs%10==0)
				{
					determineBaseline();
				}else
				{
					try {
	   		 			sleep(2500);
	   		 		} catch (InterruptedException e) {
	   		 			// TODO Auto-generated catch block
	   		 			e.printStackTrace();
	   		 		}
	   		 		if(recorder.getMaxAmplitude() > baseline)
	   		 		{
	   		 			mBinder.incrementCount();
	   		 			sendBroadcast(new Intent(CUSTOM_ACTION).putExtra(MSG, 0));
	   		 		}
				}
   		 	}	
			
		}

		private void determineBaseline() {
			Log.v(getClass().getName(),"AudioProcessing: determineBaseline ");
			sendBroadcast(new Intent(CUSTOM_ACTION).putExtra(MSG, 1));
			int max = 0;
			int seconds = 10;
			for(int i = 0;i<4*seconds;i++)
			{
			try {
		 			sleep(250);
		 		} catch (InterruptedException e) {
		 			// TODO Auto-generated catch block
		 			e.printStackTrace();
		 		}
		 		int amplitude = recorder.getMaxAmplitude();
		 		if(max < amplitude) max = amplitude;
			}
			baseline = max;
			mBinder.setBaseline(baseline);
			sendBroadcast(new Intent(CUSTOM_ACTION).putExtra(MSG, 2));
		}

		private void startRecording() {
			Log.v(getClass().getName(),"AudioProcessing: startRecording ");
			recorder = new MediaRecorder();
   		 	recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
   		 	recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
   		 	recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
   		 	
   		 	final String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Snore_Counter/.";
   		 	
   		 	//Try to make a directory
   		 	final File directory = new File(path).getParentFile();
   		 	if(directory.exists() && directory.mkdirs()) sendBroadcast(new Intent(CUSTOM_ACTION).putExtra(MSG,-2)); 
   		 	
   		 	//Check if sdcard is mounted
   		 	if(!(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))) sendBroadcast(new Intent(CUSTOM_ACTION).putExtra(MSG,-3));
   		 	
   		 	recorder.setOutputFile(path + System.currentTimeMillis() +"_Test.mp3");
   		 
   		 	try {
   		 		recorder.prepare();
   			
   		 	} catch (IllegalStateException e) {
   		 		e.printStackTrace();
   		 	} catch (IOException e) {
   		 		e.printStackTrace();
   		 	}
   		
   		 	recorder.start();
			
		}

		public void close(){ stopped = true;}
	}
	
	@Override
	public void onDestroy()
	{
		Log.v(getClass().getName(),"onDestroy");
		if(mThread != null) mThread.close();
		wl.release();
		super.onDestroy();
	}
}
